#include "DbusContext.hpp"

#include "LogCollection.hpp"

using LogCollector::Severity;
using LogCollector::Logger;
using LogCollector::ReturnStatus;

DbusContext::DbusContext(
    const std::string& aServiceName, const std::string& aServicePath, const std::string& aServiceInterface)
: mServiceName(aServiceName)
, mServicePath(aServicePath)
, mServiceInterface(aServiceInterface)
{
}

DbusContext::~DbusContext()
{
    for (auto& slot : mSlots) {
        sd_bus_slot_unref(slot);
    }
    mSlots.clear();

    if (mDbus) {
        sd_bus_unref(mDbus);
        mDbus = nullptr;
    }
        
    if (mEvent) {
        sd_event_unref(mEvent);
        mEvent = nullptr;
    }
}

void DbusContext::run()
{
    if (!init()) {
        return;
    }

    if (!prepare()) {
        return;
    }

    eventloop();
}

bool DbusContext::init()
{
   //! 创建事件循环对象(内部自带epoll线程池)
    auto ret = sd_event_new(&mEvent);
    if (ret < 0) {
        SS_LOG(Severity::Level::ERROR,
            "Failed to create event: %s", strerror(-ret));
        return false;
    }

    //! 创建并打开连接到 DBus 系统总线
    ret = sd_bus_open_system(&mDbus);
    if (ret < 0) {
        SS_LOG(Severity::Level::ERROR,
            "Failed to connect to system bus: %s", strerror(-ret));
        sd_event_unref(mEvent);
        return false;
    }

    //! 把dbus挂到事件循环中，框架自动处理读写
    ret = sd_bus_attach_event(mDbus, mEvent, 0);
    if (ret < 0) {
        SS_LOG(Severity::Level::ERROR,
            "sd_bus_attach_event: %s", strerror(-ret));
        sd_bus_unref(mDbus);
        sd_event_unref(mEvent);
        return false;
    }

    //! 通过 DBus 注册我们的服务
    ret = sd_bus_request_name(mDbus, mServiceName.c_str(), 0);
    if (ret < 0) {
        SS_LOG(Severity::Level::ERROR,
            "Failed to register object to bus: %s", strerror(-ret));
        sd_bus_unref(mDbus);
        sd_event_unref(mEvent);
        return false;
    }

    return true;
}

bool DbusContext::eventloop()
{
    if (!mDbus || !mEvent) {
        return false;
    }
    auto ret = sd_event_loop(mEvent);
    if (ret < 0) {
        SS_LOG(Severity::Level::ERROR,
            "Failed to create event loop: %s", strerror(-ret));
        sd_bus_unref(mDbus);
        sd_event_unref(mEvent);
        return false;
    }

    return true;
}
